Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThis PR threads an optional RBAC Changes
Sequence DiagramsequenceDiagram
participant Client
participant Engine
participant ServiceMacro
participant HandlerRegistry
participant InvocationHandler
participant FunctionHandler
participant Session as RBAC_Session
Client->>Engine: register_function_handler_with_session(SessionHandler)
Engine->>HandlerRegistry: store SessionHandler
Client->>Engine: invoke_function(input, maybe_session)
Engine->>InvocationHandler: handle_invocation(input, session)
alt session provided
InvocationHandler->>Session: clone session
InvocationHandler->>FunctionHandler: call_handler(invocation_id, input, Some(session))
FunctionHandler->>FunctionHandler: user_handler(input, Some(session))
else no session
InvocationHandler->>FunctionHandler: call_handler(invocation_id, input, None)
FunctionHandler->>FunctionHandler: user_handler(input, None)
end
FunctionHandler-->>Engine: FunctionResult
alt get_functions with session
Client->>Engine: get_functions(session)
Engine->>HandlerRegistry: filter by RBAC using session
HandlerRegistry-->>Engine: allowed_functions
Engine-->>Client: filtered_function_list
else get_functions without session
Engine-->>Client: all_functions
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
engine/src/engine/mod.rs (1)
672-754:⚠️ Potential issue | 🔴 CriticalDon't bypass the normal dispatch path after middleware.
This branch returns before the
match actionlogic and invokesremember_invocation()directly. With middleware enabled,TriggerAction::Enqueuebecomes an immediate invoke,TriggerAction::Voidstill sends anInvocationResult, and the_caller_worker_idinjection fromspawn_invoke_function()is lost. Please feed the enriched payload back through the same post-action dispatch path so middleware doesn't change invocation semantics.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@engine/src/engine/mod.rs` around lines 672 - 754, The middleware branch is bypassing the normal dispatch path by calling remember_invocation() directly (losing semantics for TriggerAction::Enqueue, TriggerAction::Void and the _caller_worker_id set by spawn_invoke_function()); instead, after obtaining enriched_payload from engine.call(&middleware_id, ...), re-enter the same post-action dispatch logic used elsewhere (the match action branch) so the enriched payload flows through the exact same code path that handles Enqueue/Void/normal invokes and preserves _caller_worker_id; in practice replace the direct call to remember_invocation/send_msg in the tokio::spawn with code that reuses the existing dispatch mechanism (or call the same helper used by spawn_invoke_function) passing enriched_payload, inv_id, function_id, traceparent and baggage so behavior remains identical to non-middleware invocations.
🧹 Nitpick comments (1)
engine/src/function.rs (1)
39-45: Avoid cloning every payload incall_handler.
datais already owned here and isn't reused after dispatch, sodata.clone()adds a full extra JSON copy to every invocation on the hot path.♻️ Proposed fix
pub async fn call_handler( self, invocation_id: Option<Uuid>, data: Value, session: Option<Arc<Session>>, ) -> FunctionResult<Option<Value>, ErrorBody> { - (self.handler)(invocation_id, data.clone(), session).await + (self.handler)(invocation_id, data, session).await }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@engine/src/function.rs` around lines 39 - 45, call_handler is cloning the owned JSON payload unnecessarily; instead of calling (self.handler)(invocation_id, data.clone(), session).await, pass the owned data directly: (self.handler)(invocation_id, data, session).await. Update this call in the call_handler function (and if the handler signature currently expects a reference, adjust the handler/type to accept Value by value or otherwise move the value) so no extra JSON copy is performed on the hot path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@engine/function-macros/src/lib.rs`:
- Around line 163-183: The helper type_contains_ident is too permissive: before
generating the SessionHandler closure you must validate the function's second
parameter shape exactly (not just that it contains the identifier "Session");
update has_session_param or add an explicit check right before constructing
SessionHandler to accept only Option<::std::sync::Arc<Session>> (or the exact
allowed variants) and otherwise emit a compile_error! with a clear message;
reference the symbols type_contains_ident, has_session_param, and SessionHandler
so the check is placed just before the SessionHandler generation block and
rejects/diagnoses unsupported shapes rather than letting the generated closure
produce opaque type errors.
---
Outside diff comments:
In `@engine/src/engine/mod.rs`:
- Around line 672-754: The middleware branch is bypassing the normal dispatch
path by calling remember_invocation() directly (losing semantics for
TriggerAction::Enqueue, TriggerAction::Void and the _caller_worker_id set by
spawn_invoke_function()); instead, after obtaining enriched_payload from
engine.call(&middleware_id, ...), re-enter the same post-action dispatch logic
used elsewhere (the match action branch) so the enriched payload flows through
the exact same code path that handles Enqueue/Void/normal invokes and preserves
_caller_worker_id; in practice replace the direct call to
remember_invocation/send_msg in the tokio::spawn with code that reuses the
existing dispatch mechanism (or call the same helper used by
spawn_invoke_function) passing enriched_payload, inv_id, function_id,
traceparent and baggage so behavior remains identical to non-middleware
invocations.
---
Nitpick comments:
In `@engine/src/function.rs`:
- Around line 39-45: call_handler is cloning the owned JSON payload
unnecessarily; instead of calling (self.handler)(invocation_id, data.clone(),
session).await, pass the owned data directly: (self.handler)(invocation_id,
data, session).await. Update this call in the call_handler function (and if the
handler signature currently expects a reference, adjust the handler/type to
accept Value by value or otherwise move the value) so no extra JSON copy is
performed on the hot path.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: a7bada93-39ae-4846-8dc0-c7964144760d
📒 Files selected for processing (21)
docs/how-to/worker-rbac.mdxengine/function-macros/src/lib.rsengine/src/condition.rsengine/src/engine/mod.rsengine/src/function.rsengine/src/invocation/mod.rsengine/src/modules/bridge_client/mod.rsengine/src/modules/engine_fn/mod.rsengine/src/modules/queue/adapters/builtin/adapter.rsengine/src/modules/queue/queue.rsengine/src/modules/telemetry/mod.rsengine/src/modules/worker/rbac_session.rsengine/tests/common/queue_helpers.rsengine/tests/dlq_redrive_e2e.rsengine/tests/queue_e2e_fanout.rsengine/tests/rabbitmq_queue_integration.rssdk/fixtures/config-test.yamlsdk/packages/node/iii-browser/package.jsonsdk/packages/node/iii/tests/rbac-workers.test.tssdk/packages/python/iii/tests/test_rbac_workers.pysdk/packages/rust/iii/tests/rbac_workers.rs
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
engine/src/engine/mod.rs (1)
1303-1314:⚠️ Potential issue | 🟠 Major
Engine::call()still strips the active session.Line 1313 hardcodes
None, so everyself.call(...)insiderouter_msg()—notably middleware and the RBAC registration hooks—invokes session-aware handlers without the worker's session. That meansregister_function_handler_with_sessioncannot actually see fields likeallowed_functionsorfunction_registration_prefixon those paths. Please add a session-aware internal call path and use it from the worker-session branches.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@engine/src/engine/mod.rs` around lines 1303 - 1314, Engine::call currently passes None for the session into self.invocations.handle_invocation (see invocations.handle_invocation(..., None, ...)), which strips the active worker session for all router_msg paths; add a session-aware internal call path that forwards the active session (the worker/session variable used in the worker-session branches) into handle_invocation and update Engine::call/router_msg to use that path for middleware, RBAC hooks and register_function_handler_with_session so those handlers can read allowed_functions and function_registration_prefix from the session.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@engine/src/engine/mod.rs`:
- Around line 1303-1314: Engine::call currently passes None for the session into
self.invocations.handle_invocation (see invocations.handle_invocation(..., None,
...)), which strips the active worker session for all router_msg paths; add a
session-aware internal call path that forwards the active session (the
worker/session variable used in the worker-session branches) into
handle_invocation and update Engine::call/router_msg to use that path for
middleware, RBAC hooks and register_function_handler_with_session so those
handlers can read allowed_functions and function_registration_prefix from the
session.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 480dd6c2-2634-4901-941d-521db4cf3e1a
📒 Files selected for processing (4)
engine/src/engine/mod.rssdk/packages/node/iii/tests/rbac-workers.test.tssdk/packages/python/iii/tests/test_rbac_workers.pysdk/packages/rust/iii/tests/rbac_workers.rs
✅ Files skipped from review due to trivial changes (1)
- sdk/packages/python/iii/tests/test_rbac_workers.py
🚧 Files skipped from review as they are similar to previous changes (1)
- sdk/packages/node/iii/tests/rbac-workers.test.ts
| engine.send_msg(&w, response).await; | ||
| }); | ||
| return Ok(()); | ||
| if !function_id.starts_with("engine::") { |
There was a problem hiding this comment.
Should we include a logger message saying this prefix is not allowed?
There was a problem hiding this comment.
it is allowed but middleware doesn't run on those
There was a problem hiding this comment.
🧹 Nitpick comments (3)
engine/src/engine/mod.rs (2)
1329-1341: Consider documenting that directcall()invocations have no session context.Direct
EngineTrait::call()passesNonefor the session parameter. This is appropriate for internal engine operations (triggers, hooks, conditions) that aren't subject to RBAC. However, this means functions invoked directly won't receive session information even if they declare a session parameter.Consider adding a doc comment to the
callmethod clarifying this behavior:/// Directly invokes a function by ID. /// /// Note: Direct calls do not propagate session context (session will be `None`). /// For session-aware invocations, use the worker-based invocation path. async fn call(...) -> ...🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@engine/src/engine/mod.rs` around lines 1329 - 1341, Add a doc comment to EngineTrait::call explaining that it purposefully passes None for the session (via the invocations.handle_invocation call) so direct/internal calls have no session context; explicitly state “session will be None” and recommend using the worker-based invocation path for session-aware calls so callers know why session parameters are not populated.
218-224: Consider adding documentation for the session-aware handler feature.Per coding guidelines for
engine/**changes, this newregister_function_handler_with_sessionAPI and session parameter support should be documented for SDK users. Consider updating:
- Rust SDK docs explaining how to declare a session parameter in
#[function]annotated methods- Examples showing session parameter usage:
fn my_func(input: MyInput, session: Option<Arc<Session>>)- Explanation of when session is available (worker connections with RBAC) vs
None(direct calls, workers without session)Would you like me to draft documentation content for the session parameter feature?
As per coding guidelines: "Check for impacts to the docs/" for engine changes.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@engine/src/engine/mod.rs` around lines 218 - 224, Add user-facing documentation for the new session-aware API: document the register_function_handler_with_session function and the session parameter semantics in the Rust SDK docs, include a small example showing a handler signature like fn my_func(input: MyInput, session: Option<Arc<Session>>) and note how to annotate with #[function], and describe when session is Some (worker connections with RBAC-enabled sessions) versus None (direct calls or workers without session). Update any relevant examples and the engine-level API docs to reference Session, SessionHandler, and SessionHandlerFn so SDK users know how to declare and consume the session parameter.engine/function-macros/src/lib.rs (1)
378-416: Fully qualify theSessiontype in generated code for better self-containment.The generated closure (line 381) uses
::std::sync::Arc<Session>whereSessionis unqualified. While this works because files using the macro with session parameters explicitly importSession(e.g.,use crate::modules::worker::rbac_session::Session), the generated code relies on this implicit import requirement. Fully qualifyingSessionwould eliminate this hidden dependency and provide clearer, more robust code.♻️ Suggested fix
- let `#handler_ident` = SessionHandler::new(move |input: Value, session: Option<::std::sync::Arc<Session>>| { + let `#handler_ident` = SessionHandler::new(move |input: Value, session: Option<::std::sync::Arc<crate::modules::worker::rbac_session::Session>>| {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@engine/function-macros/src/lib.rs` around lines 378 - 416, The generated closure uses an unqualified Session type; change the closure signature and all references of ::std::sync::Arc<Session> inside handler_and_registration (the SessionHandler::new invocation and any return/param types used there) to the fully-qualified path (e.g., ::crate::modules::worker::rbac_session::Session) so the macro output is self-contained; update both the closure parameter type and any Arc<...> occurrences before calling engine.register_function_handler_with_session to use the fully-qualified Session type.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@engine/function-macros/src/lib.rs`:
- Around line 378-416: The generated closure uses an unqualified Session type;
change the closure signature and all references of ::std::sync::Arc<Session>
inside handler_and_registration (the SessionHandler::new invocation and any
return/param types used there) to the fully-qualified path (e.g.,
::crate::modules::worker::rbac_session::Session) so the macro output is
self-contained; update both the closure parameter type and any Arc<...>
occurrences before calling engine.register_function_handler_with_session to use
the fully-qualified Session type.
In `@engine/src/engine/mod.rs`:
- Around line 1329-1341: Add a doc comment to EngineTrait::call explaining that
it purposefully passes None for the session (via the
invocations.handle_invocation call) so direct/internal calls have no session
context; explicitly state “session will be None” and recommend using the
worker-based invocation path for session-aware calls so callers know why session
parameters are not populated.
- Around line 218-224: Add user-facing documentation for the new session-aware
API: document the register_function_handler_with_session function and the
session parameter semantics in the Rust SDK docs, include a small example
showing a handler signature like fn my_func(input: MyInput, session:
Option<Arc<Session>>) and note how to annotate with #[function], and describe
when session is Some (worker connections with RBAC-enabled sessions) versus None
(direct calls or workers without session). Update any relevant examples and the
engine-level API docs to reference Session, SessionHandler, and SessionHandlerFn
so SDK users know how to declare and consume the session parameter.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: bb075b2e-58ba-4073-97ef-cacc8291d78e
📒 Files selected for processing (4)
engine/function-macros/src/lib.rsengine/src/condition.rsengine/src/engine/mod.rssdk/packages/node/iii-browser/README.md
Summary by CodeRabbit
New Features
Tests
Chores